# Introduction

The **TagInput** component is a text input component that adds values as tags.

## Highlights

- Backspace (when cursor is at position 0 in the input) removes items
- Enter keypress appends items to the list
- Define (or disable) a `separator` to add multiple items at once (splits on comma and new line by default)
- Values prop is controlled, it's up to consumers to control adding/removing items via `onAdd`, `onRemove`, or conveniently using `onChange` to get the new array.
- Prevent input clearing (for instance if an item is invalid) by returning `false` during `onAdd` or `onChange`

## Basic controlled TagInput

```jsx
function BasicTagInputExample() {
  const [values, setValues] = React.useState(['Kauri', 'Willow'])
  return (
    <TagInput
      inputProps={{ placeholder: 'Add trees...' }}
      values={values}
      onChange={(values) => {
        setValues(values)
      }}
    />
  )
}
```

## Custom tag submit key

You can customize the key to submit a new tag by either passing in `space` or `enter`.
This will be the key by which to submit a tag as a user is typing in the input.

```jsx
function SubmitKeyTagInputExample() {
  const [values, setValues] = React.useState(['Kauri', 'Willow'])
  return (
    <TagInput
      inputProps={{ placeholder: 'Add trees...' }}
      values={values}
      tagSubmitKey="space"
      onChange={(values) => {
        setValues(values)
      }}
    />
  )
}
```

## Full width TagInput

Use the `width` property to control the width of the `TagInput`.

```jsx
function FullWidthTagInputExample() {
  const [values, setValues] = React.useState(['Kauri', 'Willow'])
  return (
    <TagInput
      inputProps={{ placeholder: 'Add trees...' }}
      values={values}
      width="100%"
      onChange={(values) => {
        setValues(values)
      }}
    />
  )
}
```

## Disabled TagInput

Use the `disabled` property to disable interactions with the `TagInput`.

```jsx
function DisabledTagInputExample() {
  const [values, setValues] = React.useState(['Kauri', 'Willow'])
  return (
    <TagInput
      inputProps={{ placeholder: 'Add trees...' }}
      values={values}
      disabled
      onChange={(values) => {
        setValues(values)
      }}
    />
  )
}
```

## Change props of tags

Use the `tagProps` to change properties of a tag.
This is useful in cases when you want to create red tags for example.

```jsx
function TagPropTagInputExample() {
  const [values, setValues] = React.useState(['Kauri', 'Willow'])
  return (
    <TagInput
      inputProps={{ placeholder: 'See red tags...' }}
      values={values}
      disabled
      tagProps={{
        color: 'red',
      }}
      onChange={(values) => {
        setValues(values)
      }}
    />
  )
}
```

## Change props of tags based on the value

In some cases you might want to change the props of a tag based on the input.
Pass a function to the `tagProps` to achieve this.

```jsx
function TagPropCallbackTagInputExample() {
  const [values, setValues] = React.useState(['Kauri', 'Willow'])
  return (
    <TagInput
      tagProps={(value) => {
        if (!value.includes('@')) return { color: 'red' }
        return {}
      }}
      inputProps={{ placeholder: 'Add email...' }}
      values={values}
      onChange={(values) => {
        setValues(values)
      }}
    />
  )
}
```

## Autocomplete

Provide an `autocompleteItems` prop to enable autocomplete functionality. Note that this array of items needs to be
manually controlled. `TagInput` will not remove items from this list after they are selected.

```jsx
function AutoCompleteTagInputExample() {
  const [values, setValues] = React.useState(['First', 'Second'])

  const allValues = React.useMemo(
    () => ['First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth', 'Seventh', 'Eighth', 'Ninth', 'Tenth'],
    []
  )
  const autocompleteItems = React.useMemo(() => allValues.filter((i) => !values.includes(i)), [allValues, values])

  return (
    <TagInput
      inputProps={{ placeholder: 'Enter something...' }}
      values={values}
      onChange={setValues}
      autocompleteItems={autocompleteItems}
    />
  )
}
```

## Using onAdd and onRemove (advanced)

In more delicate use cases you can use `onAdd` and `onRemove` instead of `onChange`.

- `onAdd/onChange` will give you strings that were entered and split (based on `separator`) and trimmed
- `onRemove/onChange` will give you the `this.props.values` with the item removed at a particular index, which could contain jsx if your `props.values` included it

_If you are using an array of strings for use `onChange` safely_, otherwise use `onAdd/onRemove`

```jsx
function OnAddOnRemoveTagInputExample() {
  const [values, setValues] = React.useState(['test@test.com'])
  return (
    <TagInput
      inputProps={{ placeholder: 'Add email...' }}
      values={values}
      onAdd={(newValues) => {
        if (newValues.some((val) => !val.includes('@'))) {
          toaster.danger('Oops, you tried entering a invalid email. Try again.')
          return
        }
        setValues([...values, ...newValues])
      }}
      onRemove={(_value, index) => {
        setValues(values.filter((_, i) => i !== index))
      }}
    />
  )
}
```
